//***************************************************************************************************
//*Variables
//***************************************************************************************************

float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 WorldIT;

//**********************************
//*Wave
//**********************************
float time = 0.0f;
float height = 1.0f;
int Direction = 0;
const float pi = 3.1416f;
bool TextureEnabled = false;
bool WaveEnabled = true;
texture Texture;

//**********************************
//*Light
//**********************************
bool LightEnabled = false;

float3 LightPos1;
float LightPower1 = 1.0f;
float4 Color1 = float4(1,1,1,1);
bool Light1Enabled = false;

float3 LightPos2;
float LightPower2 = 1.0f;
float4 Color2 = float4(1,1,1,1);
bool Light2Enabled = false;

float3 LightPos3;
float LightPower3 = 1.0f;
float4 Color3 = float4(1,1,1,1);
bool Light3Enabled = false;

float3 LightPos4;
float LightPower4 = 1.0f;
float4 Color4 = float4(1,1,1,1);
bool Light4Enabled = false;

// TODO: add effect parameters here.


//***************************************************************************************************
//*Input and Ouput Structs
//***************************************************************************************************

struct VertexWaveInput
{
    float4 Position : POSITION0;
    float3 Normal	: NORMAL;
    float2 Tex		: TEXCOORD0;
};

struct VertexWaveOutput
{
    float4 Position   : POSITION0;
    float2 Tex		  : TEXCOORD0;
    float3 Normal	  : TEXCOORD1;
    float3 Position3D : TEXCOORD2;
};

struct PointLightVertexOutput
{
	float3 Normal;
	float3 Position3D;
};

//***************************************************************************************************
//*Functions
//***************************************************************************************************

float DotProduct(float3 lightPos, float3 pos3D, float3 normal)
{
	float3 lightDir = normalize(pos3D - lightPos);
	return dot(-lightDir, normal);
}

PointLightVertexOutput PointLightVertex(float4 Position, float3 Normal)
{
	PointLightVertexOutput output;
	
	output.Normal = normalize(mul(Normal, (float3x3)World));
	output.Position3D = mul(Position, World);
	
	return output;
}

float4 PointLightPixel(float3 Position3D, float3 Normal)
{
	float diffuseLightingFactor;
	
	float4 color = float4(1,1,1,1);
	float4 tmpColor;

	if(Light1Enabled)
	{
		diffuseLightingFactor = DotProduct(LightPos1, Position3D, Normal);
		diffuseLightingFactor = saturate(diffuseLightingFactor);
		diffuseLightingFactor *= LightPower1;
		
		tmpColor = mul(diffuseLightingFactor, Color1);
		color = float4((tmpColor.r + color.r)/2, (tmpColor.g + color.g)/2,(tmpColor.b + color.b)/2,(tmpColor.a + color.a)/2);
	}
	if(Light2Enabled)
	{
		diffuseLightingFactor = DotProduct(LightPos2, Position3D, Normal);
		diffuseLightingFactor = saturate(diffuseLightingFactor);
		diffuseLightingFactor *= LightPower2;
		
		tmpColor = mul(diffuseLightingFactor, Color2);	
		color = float4((tmpColor.r + color.r)/2, (tmpColor.g + color.g)/2,(tmpColor.b + color.b)/2,(tmpColor.a + color.a)/2);		
	}
	
	if(Light3Enabled)
	{
		diffuseLightingFactor = DotProduct(LightPos3, Position3D, Normal);
		diffuseLightingFactor = saturate(diffuseLightingFactor);
		diffuseLightingFactor *= LightPower3;
		
		tmpColor = mul(diffuseLightingFactor, Color3);	
		color = float4((tmpColor.r + color.r)/2, (tmpColor.g + color.g)/2,(tmpColor.b + color.b)/2,(tmpColor.a + color.a)/2);
	}
	if(Light4Enabled)
	{
		diffuseLightingFactor = DotProduct(LightPos4, Position3D, Normal);
		diffuseLightingFactor = saturate(diffuseLightingFactor);
		diffuseLightingFactor *= LightPower4;
		
		tmpColor = mul(diffuseLightingFactor, Color4);	
		color = float4((tmpColor.r + color.r)/2, (tmpColor.g + color.g)/2,(tmpColor.b + color.b)/2,(tmpColor.a + color.a)/2);
	}
	
	return color;
}

//***************************************************************************************************
//*Vertex and Pixel Shader Functions
//***************************************************************************************************

VertexWaveOutput VertexShaderLightWave(VertexWaveInput input)
{
    VertexWaveOutput output;
    
    if(WaveEnabled)
    {
		float4 pos[7];
	    
		//Used to changed which direction the wave is drawn
		pos[0] = input.Position; //X direction
		pos[1] = input.Position; //Y direction
		pos[2] = input.Position; //Z direction
		pos[3] = input.Position; //X & Y direction
		pos[4] = input.Position; //X & Z direction
		pos[5] = input.Position; //Y & Z direction
		pos[6] = input.Position; //X & Y & Z direction
	    
		//input.Position.z += sin(time * (input.Position.x + input.Position.y + input.Position.z) * pi) * height;
	    
		pos[0].x += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		
		pos[1].y += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		
		pos[2].z += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;

		pos[3].x += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		pos[3].y += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;

		pos[4].x += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		pos[4].z += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		
		pos[5].y += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		pos[5].z += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;

		pos[6].x += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		pos[6].y += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
		pos[6].z += sin(time * (input.Tex.x + input.Tex.y) * pi) * height;
					
		// Do transformation
		float4 worldPosition = mul(pos[Direction], World);
		float4 viewPosition  = mul(worldPosition, View);
		output.Position      = mul(viewPosition, Projection);		
    
    }
    else
    {
		float4 worldPosition = mul(input.Position, World);
		float4 viewPosition  = mul(worldPosition, View);
		output.Position      = mul(viewPosition, Projection);		
    }
    
    output.Normal = input.Normal;
    
	output.Tex = input.Tex;			
	
	PointLightVertexOutput PlightOut = PointLightVertex(output.Position, input.Normal);	
	
	if(LightEnabled)
		output.Normal = PlightOut.Normal;
	
	output.Position3D = PlightOut.Position3D;
	
	
    return output;
}

sampler Sampler = sampler_state
{
    Texture = (Texture);
    
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Linear;
    
    AddressU = Wrap;
    AddressV = Wrap;
};

float4 PixelShaderLightWave(VertexWaveOutput input) : COLOR0
{
	float4 color = float4(1,1,1,1);
	
	
	if (TextureEnabled)
    {
		color = tex2D (Sampler, input.Tex);
		if(LightEnabled)
			color *= PointLightPixel(input.Position3D, input.Normal);
	}
	else
	{			
		if(LightEnabled)
			color = PointLightPixel(input.Position3D, input.Normal);
	}
	
    return color;
}

//***************************************************************************************************
//*
//***************************************************************************************************

technique LightWave
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderLightWave();
        PixelShader  = compile ps_2_0 PixelShaderLightWave();
    }
}